package com.atguigu.java2;

/**
 * 线程通信的例子，使用两个线程打印1-100。线程1，线程2 交替打印
 *
 * 涉及到的三个方法：
 * wait(); 一旦执行此方法，当前线程进入阻塞状态，并释放同步监视器。
 * notify();一旦执行此方法，就会唤醒被wait的一个线程。如果有多个线程被wait，就唤醒优先级最高的那个。
 * notifyAll();一旦执行此方法，就会唤醒所有被wait的线程
 *
 * 说明：
 * 1.wait()、notify()、notifyAll()三个方法必须使用在同步代码块或者同步方法中。
 * 2.wait()、notify()、notifyAll()这三个方法的调用者必须是同步代码或者同步方法中的同步监视器。
 * 否则会出现IllegalMonitorStateException异常
 * 3.wait()、notify()、notifyAll()三个方法是定义在java.lang.Object类中。
 *
 *
 * 面试题：sleep()和wait()的异同？
 * 1.相同点：一旦执行方法。都可以使得当前的线程进入阻塞状态
 * 2.不同点：
 *      1.两个方法声明的位置不同：Thread类中声明的sleep(),Object类中声明的wait()
 *      2.调用的范围不同：sleep()可以在任何需要的场景下调用；wait()必须被同步监视器调用（也就是在同步代码块或者同步方法调用的）
 *      3.关于是否释放同步监视器：如果两个方法都使用在同步代码块或者同步方法中，sleep()不会释放同步监视器，wait()会释放同步监视器。
 * @Description
 * @Author codingBee
 * @Date 2020/9/2/21:33
 */
public class CommunicationTest {
    public static void main(String[] args) {
        Number number = new Number();
        Thread thread1 = new Thread(number);
        Thread thread2 = new Thread(number);
        thread1.setName("线程1");
        thread2.setName("线程2");
        thread1.start();
        thread2.start();
    }
}

class Number implements Runnable {
    private int number = 1;
    Object object =  new Object();
    @Override
    public void run() {
        for (; true; ) {
            synchronized (object) {
                //唤醒其他线程
                object.notify();
                if (number < 101) {
                    System.out.println(Thread.currentThread().getName() + ":" + number);
                    number++;
                    try {
                        //使得调用wait()方法的线程进入阻塞状态，然后把锁释放
                        object.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } else {
                    break;
                }
            }
        }
    }
}